package com.googlecode.functionalcollections;

import java.util.Collection;
import java.util.List;
import java.util.NoSuchElementException;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;


/**
 * Functional extension of {@link Iterable}, most methods are simple wrapper of {@link Iterables}.
 * 
 * @author James
 * @see Iterable
 * @see Iterables
 * 
 */
public interface FunctionalIterable<F> extends Iterable<F> {
	
	void each(Block<? super F> block);

	boolean any(Predicate<? super F> predicate);
	
	boolean all(Predicate<? super F> predicate);
	
	/**
	 * @see Iterables#find(Iterable, Predicate)
	 * @see #detect(Predicate)
	 */
	F find(Predicate<? super F> predicate) throws NoSuchElementException;

	/**
	 * Returns the first element in that satisfies the given predicate, <code>null</code>
	 * if no element satisfies.
	 * @see #find(Predicate)
	 */
	F detect(Predicate<? super F> predicate);
	
	FunctionalIterable<F> filter(Predicate<? super F> predicate);

	<T> FunctionalIterable<T> transform(Function<? super F, ? extends T> function);

	<M> M inject(M initial, Injector<M, F> injector);
	
	int size();
	
	boolean contains(Object element);
	
	boolean removeAll(Collection<?> elementsToRemove);
	
	boolean retainAll(Collection<?> elementsToRetain);
	
	boolean elementsEqual(Iterable<?> target);
	
	String toString();
	
	F getOnlyElement();
	
	F getOnlyElement(F defaultValue);
	
	F[] toArray(Class<F> type);
	
	int frequency(Object element);
	
	FunctionalIterable<F> cycle();
	
	FunctionalIterable<F> contract(Iterable<? extends F> target);
	
	FunctionalIterable<List<F>> partition(int size);
	
	FunctionalIterable<List<F>> paddedPartition(int size);
	
	F get(int position);
	
	F getLast();
	
	boolean isEmpty();

}
